/*
 * Copyright © OpenAtom Foundation.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *     http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package io.iec.edp.caf.generator.item;

import java.util.ArrayList;

import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;

import io.iec.edp.caf.generator.BaseGenerator;
import io.iec.edp.caf.generator.baseInfo.ClassGenerateInfo;
import io.iec.edp.caf.generator.baseInfo.CompilationUnitInfo;
import io.iec.edp.caf.generator.baseInfo.TypeGeneratorInfo;
import io.iec.edp.caf.generator.baseInfo.TypeInfo;
import io.iec.edp.caf.generator.field.FieldGenerator;
import io.iec.edp.caf.generator.method.ClassMethodGenerator;
import io.iec.edp.caf.generator.property.ClassPropertyGenerator;

public abstract class ClassGenerator extends ItemInfoGenerator {

    protected ClassGeneratorContext getContext() {
        return (ClassGeneratorContext) super.getContext();
    }

    protected ClassGenerator(CompilationUnitInfo projectInfo) {
        super(projectInfo);
    }


    @Override
    protected void beforeGenerate() {
        super.beforeGenerate();
    }

    @Override
    protected void setParent() {
        TypeInfo parentType = setParentClass();
        if (parentType == null) {
            return;
        }
        buildParentClass(setParentClass());
    }

    //CreateItemInfoContext
    @Override
    protected ItemGeneratorContext createItemInfoContext() {
        ClassGeneratorContext context = createClassInfoContext();
        // ClassGenerateInfo classInfo = ClassGenerateInfo.Create();
        // context.ItemInfo = classInfo;
        return context;
    }

    @Override
    protected TypeGeneratorInfo createItemInfo() {
        return ClassGenerateInfo.create();
    }

    protected abstract ClassGeneratorContext createClassInfoContext();

    //CreateChildGenerators
    @Override
    protected final ArrayList<BaseGenerator> createChildGenerators() {
        ArrayList<BaseGenerator> childGenerators = super.createChildGenerators();
        if (childGenerators == null) {
            childGenerators = new ArrayList<BaseGenerator>();
        }

        addClassExtendChildGenrators(childGenerators);

        addConstructorGenerators(childGenerators);

        addPropertyGenerators(childGenerators);

        addMethodGenerators(childGenerators);

        addFieldGenerators(childGenerators);

        return childGenerators;
    }

    private void addClassExtendChildGenrators(ArrayList<BaseGenerator> generators) {
        ArrayList<BaseGenerator> extendClassGenrators = createClassExtendChildGenrators();
        if (extendClassGenrators != null && extendClassGenrators.size() > 0) {
            generators.addAll(extendClassGenrators);
        }
    }

    private void addConstructorGenerators(ArrayList<BaseGenerator> generators) {
        ArrayList<ClassMethodGenerator> constructorGenerators = createConstructorGenerators();
        if (constructorGenerators != null && constructorGenerators.size() > 0) {
            generators.addAll(constructorGenerators);
        }
    }

    private void addPropertyGenerators(ArrayList<BaseGenerator> generators) {
        ArrayList<ClassPropertyGenerator> propertyGenerators = createPropertyGenerators();
        if (propertyGenerators != null && propertyGenerators.size() > 0) {
            generators.addAll(propertyGenerators);
        }
    }

    private void addMethodGenerators(ArrayList<BaseGenerator> generators) {
        ArrayList<ClassMethodGenerator> methodGenerators = createMethodGenerators();
        if (methodGenerators != null && methodGenerators.size() > 0) {
            generators.addAll(methodGenerators);
        }
    }

    private void addFieldGenerators(ArrayList<BaseGenerator> generators) {
        ArrayList<FieldGenerator> fieldGenerators = createFieldGenerator();
        if (fieldGenerators != null && fieldGenerators.size() > 0) {
            generators.addAll(fieldGenerators);
        }
    }

    protected ArrayList<BaseGenerator> createClassExtendChildGenrators() {
        return null;
    }

    protected ArrayList<ClassMethodGenerator> createConstructorGenerators() {
        return null;
    }

    protected ArrayList<ClassPropertyGenerator> createPropertyGenerators() {
        return null;
    }

    protected ArrayList<ClassMethodGenerator> createMethodGenerators() {
        return null;
    }

    protected ArrayList<FieldGenerator> createFieldGenerator() {
        return null;
    }

    @Override
    protected void afterGenerate() {
        super.afterGenerate();
//		ExtendAfterGenerate();
        compileUnit.addType(getContext().getItemInfo().getTypeResult());
    }
//	protected void ExtendAfterGenerate() {
//		java.util.ArrayList<MemberDeclarationSyntax> methods = GetExtendMethods();
//		if (methods == null) {
//			return;
//		}
//		Context.ItemInfo.ClassResult = Context.ItemInfo.ClassResult
//				.AddMembers(methods.toArray(new MemberDeclarationSyntax[] {}));
//	}
//
//	protected java.util.ArrayList<MemberDeclarationSyntax> GetExtendMethods() {
//		return null;
//	}


    @Override
    protected final void setAccessModifier() {
        getContext().getItemInfo().setModifiers(getAccessModifier());
    }

    protected abstract ArrayList<ModifierKeyword> getAccessModifier();

    private void buildParentClass(TypeInfo info) {
        String typeFullName = info.getTypeFullName();
        if (typeFullName != null)
            addImport(typeFullName);
        getContext().getItemInfo().setSuperClass(info);
    }

    protected TypeInfo setParentClass() {
        return null;
    }

}
